package org.abc.fund.controller.trade;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import org.abc.fund.controller.trade.response.TradeOrderResponse;
import org.abc.fund.entity.trade.TradeOrder;
import org.abc.fund.service.trade.TradeService;
import org.abc.fund.service.trade.request.CreateTradeOrderRequest;
import org.abc.fund.service.trade.request.SettleOrderRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.abc.fund.service.trade.request.CorrectionRequest;
import java.util.List;
import java.util.stream.Collectors;

import java.util.Map;

@RestController
@RequestMapping("/api/trade")
public class TradeController {

  private final TradeService tradeService;

  public TradeController(TradeService tradeService) {
    this.tradeService = tradeService;
  }

  @Data
  @Builder
  @AllArgsConstructor
  public static class PageResponse<T> {
    private List<T> content;
    private long totalElements;
    private int totalPages;
  }

  @PostMapping("/order")
  public ResponseEntity<TradeOrderResponse> createTradeOrder(
      @RequestBody CreateTradeOrderRequest request) {
    TradeOrder order = tradeService.createTradeOrder(request);
    return new ResponseEntity<>(TradeOrderResponse.fromEntity(order), HttpStatus.CREATED);
  }

  @PostMapping("/order/{id}/approve")
  public ResponseEntity<TradeOrderResponse> approveTradeOrder(
      @PathVariable Long id, @RequestBody Map<String, Long> payload) {
    Long approverId = payload.get("approverId");
    TradeOrder order = tradeService.approveTradeOrder(id, approverId);
    return ResponseEntity.ok(TradeOrderResponse.fromEntity(order));
  }

  @PostMapping("/order/{id}/reject")
  public ResponseEntity<TradeOrderResponse> rejectTradeOrder(
      @PathVariable Long id, @RequestBody Map<String, Object> payload) {
    Long approverId = ((Number) payload.get("approverId")).longValue();
    String reason = (String) payload.get("reason");
    TradeOrder order = tradeService.rejectTradeOrder(id, approverId, reason);
    return ResponseEntity.ok(TradeOrderResponse.fromEntity(order));
  }

  @GetMapping("/order/{id}")
  public ResponseEntity<TradeOrderResponse> getTradeOrderDetails(@PathVariable Long id) {
    return tradeService
        .getTradeOrderDetails(id)
        .map(TradeOrderResponse::fromEntity)
        .map(ResponseEntity::ok)
        .orElse(ResponseEntity.notFound().build());
  }

  @PostMapping("/order/{id}/settle")
  public ResponseEntity<TradeOrderResponse> settleTradeOrder(
      @PathVariable Long id, @RequestBody SettleOrderRequest request) {
    TradeOrder order = tradeService.settleOrder(id, request);
    return ResponseEntity.ok(TradeOrderResponse.fromEntity(order));
  }

  @GetMapping("/orders/failed")
  public ResponseEntity<List<TradeOrderResponse>> getFailedOrders() {
    List<TradeOrder> orders = tradeService.findFailedOrders();
    List<TradeOrderResponse> response =
        orders.stream().map(TradeOrderResponse::fromEntity).collect(Collectors.toList());
    return ResponseEntity.ok(response);
  }

  @PostMapping("/corrections")
  public ResponseEntity<TradeOrderResponse> createCorrection(
      @RequestBody CorrectionRequest request) {
    TradeOrder correctionOrder = tradeService.correctFailedTrade(request);
    return new ResponseEntity<>(TradeOrderResponse.fromEntity(correctionOrder), HttpStatus.CREATED);
  }

  @GetMapping("/orders/pending")
  public ResponseEntity<List<TradeOrderResponse>> getPendingOrders() {
    List<TradeOrder> pendingOrders = tradeService.findPendingOrders();
    List<TradeOrderResponse> responses =
        pendingOrders.stream().map(TradeOrderResponse::fromEntity).collect(Collectors.toList());
    return ResponseEntity.ok(responses);
  }

  @GetMapping("/orders/page")
  public ResponseEntity<PageResponse<TradeOrderResponse>> getPagedOrders(
      @RequestParam int page,
      @RequestParam int size,
      @RequestParam Long userId,
      @RequestParam(required = false) String status) {
    Pageable pageable = PageRequest.of(page, size);
    Page<TradeOrder> orderPage = tradeService.getOrdersByUserIdAndStatus(userId, status, pageable);
    Page<TradeOrderResponse> responsePage = orderPage.map(TradeOrderResponse::fromEntity);
    PageResponse<TradeOrderResponse> customResponse =
        PageResponse.<TradeOrderResponse>builder()
            .content(responsePage.getContent())
            .totalElements(responsePage.getTotalElements())
            .totalPages(responsePage.getTotalPages())
            .build();
    return ResponseEntity.ok(customResponse);
  }
}
